import { Aggregator } from "./aggregator";
import { Context, Options, ProcessingMode } from "./core";
import { Cursor } from "./cursor";
import {  AnyObject } from "./types";
import { Query } from "./query";
import { createUpdater, update } from "./updater";

// 异步模块

import { AsyncSource, AsyncQuery, AsyncAggregator,OpenedSymbol } from "./async";
import { Source } from "./lazy";

export { Aggregator } from "./aggregator";
export { Context, ProcessingMode } from "./core";
export { Query } from "./query";
export { createUpdater, update } from "./updater";

// // 异步模块导出
// export { AsyncQuery } from "./async/query";
// // export { AsyncAggregator } from "./async/aggregator";
export { AsyncCursor , OpenableAsyncIterable} from "./async";

/**
 * Finds documents in a collection that match the specified criteria.
 *
 * @template T - The type of the documents in the collection.
 * @param collection - The source collection to search.
 * @param criteria - The query criteria to filter the documents.
 * @param projection - Optional. Specifies the fields to include or exclude in the returned documents.
 * @param options - Optional. Additional options to customize the query behavior.
 * @returns A `Cursor` object that allows iteration over the matching documents.
 */
export function find<T>(
  collection: Source,
  criteria: AnyObject,
  projection?: AnyObject,
  options?: Partial<Options>
): Cursor<T> {
  return new Query(criteria, options).find<T>(collection, projection);
}

/**
 * Performs an aggregation operation on the provided collection using the specified pipeline.
 *
 * @param collection - The input data source to aggregate.
 * @param pipeline - An array of aggregation stages to process the collection.
 * @param options - Optional settings to customize the aggregation behavior.
 * @returns The result of the aggregation as an array of objects.
 */
export function aggregate(
  collection: Source,
  pipeline: AnyObject[],
  options?: Partial<Options>
): AnyObject[] {
  return new Aggregator(pipeline, options).run(collection);
}

/**
 * Performs an asynchronous aggregation operation on the provided collection using the specified pipeline.
 *
 * @param collection - The input data source to aggregate. Can be any synchronous or asynchronous iterable.
 * @param pipeline - An array of aggregation stages to process the collection.
 * @param options - Optional settings to customize the aggregation behavior.
 * @returns An async iterator that yields the results of the aggregation pipeline.
 */
export function aggregateAsync(
  collection: AsyncSource,
  pipeline: AnyObject[],
  options?: Partial<Options>
): Promise<AnyObject[]> {
  return new AsyncAggregator(pipeline, options as Options).run(collection);
}

/**
 * Returns an async cursor that wraps an async source with query capabilities.
 *
 * @template T - The type of the objects returned by the cursor.
 * @param collection - The input data source to query.
 * @param criteria - The query selector for filtering the data.
 * @param projection - The projection specification for shaping the returned data.
 * @param options - Optional settings to customize the query behavior.
 * @returns An async cursor for iterating over the query results.
 */
export function findAsync<T>(
  collection: AsyncSource,
  criteria: AnyObject,
  projection?: AnyObject,
  options?: Partial<Options>
): any {
  return new AsyncQuery(criteria, options).findAsync<T>(collection, projection);
}

// default interface for ES6 modules
export default {
  Aggregator,
  Context,
  ProcessingMode,
  Query,
  aggregate,
  createUpdater,
  find,
  update,
  // 异步接口
  AsyncQuery,
  AsyncAggregator,
  OpenedSymbol,
  findAsync,
  aggregateAsync
};